package com.draby.starfantasymaze.methods.game;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.TextView;

import androidx.annotation.NonNull;

import org.jetbrains.annotations.NotNull;

import java.util.Timer;
import java.util.TimerTask;

public class GameTimer {
    /* 计时需要用到的属性 */
    private int millisecond;
    private int second;
    private int minute;
    /* 用于计算通关时间 */
    public int getMillisecond() {
        return millisecond;
    }
    public int getSecond() {
        return second;
    }
    public int getMinute() {
        return minute;
    }

    private static final int DELAY = 20;
    private static final int PERIOD = 20;

    /* 计时器相关需要的东西 */
    private Timer timer;
    private TimerTask task;
    private Handler handler;

    /* 计时所显示的控件 */
    private final TextView textView;

    /**
     * 含参构造函数，创建游戏计时器必须传入一个非空的文本控件
     * @param textView 非空的文本控件，用来显示计时
     */
    public GameTimer(@NotNull TextView textView) {
        this.textView = textView;
        initial();
    }

    /**
     * 初始化计时器
     */
    private void initial() {
        millisecond = 0;
        second = 0;
        minute = 0;
        timer = new Timer();
        task = getTask();
        handler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                textView.setText(String.valueOf(msg.obj));
            }
        };
    }

    /**
     * 抽取出执行的任务，让计时器可以暂停
     * @return 计时器执行的任务
     */
    private TimerTask getTask() {
        return new TimerTask() {
            @Override
            public void run() {
                // 每次执行将毫秒数加2(实际时间是增加20毫秒)
                // 至于为什么是加2而不是加1...模拟器运行时加1会有明显延迟，虽然手机没问题，但考虑考虑配置比较低的手机...
                millisecond += 2;
                // 判断是否需要进位到秒
                if (millisecond >= 100) {
                    // 进位则将毫秒数减100，秒数加1
                    millisecond -= 100;
                    second++;
                    // 判断是否需要进位到分，若毫秒不进位则秒一定不会进位，所以可以放在 if 中来判断
                    if (second >= 60) {
                        // 进位则将秒数减100，分钟数加1
                        second -= 60;
                        minute++;
                    }
                }
                // 以自定义格式显示到文本控件上
                @SuppressLint("DefaultLocale") String time = String.format("%02d:%02d:%02d", minute, second, millisecond);
                // 由于线程安全问题，非创建控件的线程不允许直接修改控件的属性值，需要借助 handler 来实现
                Message message = new Message();
                message.obj = time;
                handler.sendMessage(message);
            }
        };
    }

    /**
     * 开始计时器
     */
    public void start() {
        // 检查计时器是否为空，为空则创建一个计时器对象
        if (timer == null) {
            timer = new Timer();
        }
        // 检查任务是否为空，为空则获取一个任务
        if (task == null) {
            task = getTask();
        }
        // 在指定的 DELAY 后开始执行任务，并且每隔 PERIOD 时间自动执行一次
        timer.schedule(task, DELAY, PERIOD);
    }

    /**
     * 暂停计时器
     */
    public void pause() {
        // 先取消任务，再取消计时器执行(大概？)
        if (task != null) {
            task.cancel();
            task = null;
        }
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    /**
     * 停止计时器，即暂停+初始化
     */
    public void stop() {
        pause();
        initial();
    }
}
